#ifndef _SOCKET_HTTP_H
#define _SOCKET_HTTP_H

#include "socket_tcpserver.h"
#include "hithread.h"
#include "http_parser.h"


const STRCPP HTTP_SERVER_IP         = "0.0.0.0";
const WORD16 HTTP_SERVER_PORT       = 8888;
const STRCPP HTTP_HEAD_VERSION      = "HTTP/1.0 ";
const STRCPP HTTP_SERVER_NAME       = "httpserver/linux c++ 1.0 suzhenhua";
const STRCPP HTTP_PAGE_DEFAULT      = "live.html";
typedef map<string, string> HeaderMap;

class CHttpInfo 
{
public:
	static STRCPP mimetype(const STRCPP& filename);
	static STRCPP respinfo(const STRCPP& respcode);
private:
	static STRMAP m_mimetype;
	static STRMAP m_respinfo;	
};

class CHttpReq : public CTcpSvrReq
{
public:
	CHttpReq(STRCPP rootdir);
    ~CHttpReq();

	virtual VOID   show();	
	virtual VOID*  clone();
    void init_http();
    BOOL recv_http();

    STRCPP get_url() { return req_url_;}

    virtual VOID   response_info(const STRCPP& info, const STRCPP& code="200");
    virtual VOID   response_file(const STRCPP& name);
	virtual VOID   response_path(const STRCPP& path);

	virtual BOOL   process();
	virtual VOID   process_POST();
	virtual VOID   process_CGI();
	virtual VOID   process_CGI_writereqbody(FILEFD fd, const STRCPP& reqbody);
	virtual VOID   process_CGI_readresponse(FILEFD fd);
	virtual VOID   process_CGI_setoneenv(const STRCPP& key, const WORD32& val);	
	virtual VOID   process_CGI_setoneenv(const STRCPP& key, const STRCPP& header);
	virtual VOID   process_CGI_setallenv();
	virtual VOID   process_CGI_runcgi();

    void socketDisconnected();
    void trim(STRCPP &s);
    void parase_path(STRCPP path);
    STRCPP get_http_action() { return req_action_;}
    STRCPP get_http_params() { return req_params_;}
    int get_content_length();
    bool req_http_html();

private:
    static int MessageBegin(http_parser *parser);
    static int Path(http_parser *parser, const char *at, size_t length);
    static int QueryString(http_parser *parser, const char *at, size_t length);
    static int Url(http_parser *parser, const char *at, size_t length);
    static int Fragment(http_parser *parser, const char *at, size_t length);
    static int HeaderField(http_parser *parser, const char *at, size_t length);
    static int HeaderValue(http_parser *parser, const char *at, size_t length);
    static int HeadersComplete(http_parser *parser);
    static int Body(http_parser *parser, const char *at, size_t length);
    static int MessageComplete(http_parser *parser);

protected:
	STRCPP m_rootdir;  //根目录
	STRCPP m_reqhead;  //请求的消息头内容
	STRCPP m_reqbody;  //请求的消息体
	STRMAP m_reqinfo;  //请求的map结构  
	WORD16 m_reqstat;  //接收请求的状态 1收消息头 2收消息体

    WORD32 m_reqsize;  //消息体的长度
	
    STRCPP req_path_;
    STRCPP req_url_;
    STRCPP req_action_;
    STRCPP req_params_;

	STRCPP m_method;

    STRCPP version_;
	STRCPP m_reqfile;
	STRCPP m_query;


    // 我们将从parser中读出这些信息
    HeaderMap m_currentHeaders;
    STRCPP m_currentHeaderField;
    STRCPP m_currentHeaderValue;

    http_parser_settings m_parserSettings;
    http_parser *m_parser;
};

class CHttpServer : public CSktApp,public HiThread
{
public:
    CHttpServer(STRCPP svrip, WORD16 svrport, STRCPP rootdir) : CSktApp(svrip, svrport)
    {
        is_run_ = false;
        setreq(new CHttpReq(rootdir));
    }

    static  VOID* callback(VOID* args);    
    virtual VOID  working();

    void start_http(void* context);
protected:
    void process();

private:
    bool is_run_;
};


#endif
